import java.util.LinkedList;


public class Pair extends Data {
	private Data car, cdr;
	
	public Pair(Data _car, Data _cdr) {
		car = _car;
		cdr = _cdr;
	}

	
	public Data car() {
		return car;
	}
	
	public Data cdr() {
		return cdr;
	}
	
	public static Data car(Pair p) {
		return p.car();
	}
	
	public static Data cdr(Pair p) {
		return p.cdr();
	}
	
	public void setCar(Data o) {
		car = o;
	}
	
	public void setCdr(Data o) {
		cdr = o;
	}
	
	public boolean eq(Pair p2) {
		return (this == p2);
	}
	
	public boolean equals(Object o) {
		return (o instanceof Data
				&& ((Data)o).isPair()
				&& car.equals(((Pair)o).car)
				&& cdr.equals(((Pair)o).cdr));
	}
	
	//**************************
	//====   IF Methods    =====
	//**************************
	public Pair makeIf(Data predicate, Data trueClause, Data elseClause) {
		Pair toReturn = new Pair(Parser.parse("if"), null); // For syntax
		LinkedList<Data> clauses = new LinkedList<Data>();
		clauses.addLast(predicate);
		clauses.addLast(trueClause);
		clauses.addLast(elseClause);
		setCdr(Primitive.list(clauses));
		return toReturn;
	}

	public Data ifClause() {
		return ((Pair)cdr()).car();
	}

	public Data trueClause() {
		return ((Pair)((Pair)cdr()).cdr()).car();
	}
	
	public Data elseClause() {
		return cdr().cdr().cdr().car();
	}

	@Override
	public boolean isAtom() {
		return false;
	}

	@Override
	public boolean isList() {
		return cdr.isList();
	}

	@Override
	public boolean isPair() {
		return true;
	}

	@Override
	public String toString() {
		return toString(true);
	}
	
	public String toString(boolean showParen) {
		StringBuffer toReturn = new StringBuffer();
		if (showParen) {
			toReturn.append("(");
		}
		toReturn.append(car.toString());
		boolean cdrIsNull = cdr.isNull();
		boolean cdrIsPair = cdr.isPair();
		if (cdrIsNull) {
			// do nothing
		} else if (cdrIsPair) {
			toReturn.append(" ");
			toReturn.append(((Pair)cdr).toString(false));
		} else {
			toReturn.append(" . ");
			toReturn.append(cdr.toString());
		}
		if (showParen) {
			toReturn.append(")");
		}
		return toReturn.toString();
	}


	@Override
	public int compareTo(Data o) {
		throw new SchavaException("Cannot compare pairs");
	}

}
